/* 
 * Copyright 2005-2008 Samuel Mello & Eduardo Schnell
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; version 2 of the License.
 * 
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 * 
 */

package datasoul.datashow;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.SpinnerNumberModel;
import javax.swing.SwingUtilities;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import datasoul.config.ConfigObj;
import datasoul.config.DisplayControlConfig;
import datasoul.render.ContentManager;
import datasoul.serviceitems.ServiceItem;
import datasoul.util.ObjectManager;

/**
 *
 * @author  Administrador
 */
public class LivePanel extends javax.swing.JPanel implements ListSelectionListener {

    /**
	 * 
	 */
	private static final long serialVersionUID = -6946986219215801662L;

	private AutomaticChanger automaticChanger;
    
    private int lastSelectedIndex;
    
    /**
     * Creates new form LivePanel
     */
    public LivePanel() {
        initComponents();
        serviceItemTable1.addTableListener(this);
        automaticChanger = new AutomaticChanger();
        serviceItemTable1.addTableKeyListener(new KeyListener(){

            @Override
            public void keyTyped(KeyEvent e) {
                // ignore
            }

            @Override
            public void keyPressed(KeyEvent e) {
                evtKeyPressed(e);
            }

            @Override
            public void keyReleased(KeyEvent e) {
                // ignore
            }

        });
    }

    public void setFocusInTable(){
        serviceItemTable1.setFocusInTable();
    }
    
    public void showItem(ServiceItem serviceItem, boolean backwards){

        ContentManager cm = ContentManager.getInstance();

        serviceItem.showItem();

        if (ConfigObj.getActiveInstance().getMonitorOutput()){
            // Update monitor template
            cm.setTemplateMonitorLive( serviceItem.getDefaultMonitorTemplate() );
        }
        
        // Setup timer
        ObjectManager.getInstance().getTimerControlPanel().setTimerFromServiceItem(serviceItem.getDuration());

        if (backwards){
            this.serviceItemTable1.setServiceItem(serviceItem, serviceItem.getRowCount()-1);
        }else{
            this.serviceItemTable1.setServiceItem(serviceItem, 0);
        }

        updateContentValues();
        
        // save the transition image just before changing the slide to avoid
        // problem when changing to a item that uses a template with different
        // alpha. This will cause a cut to the first slide, without any transition,
        // but at least is not buggy
        cm.saveTransitionImage();
        
        cm.slideChange(0);
        
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        serviceItemTable1 = new datasoul.serviceitems.ServiceItemTable();
        jPanel1 = new javax.swing.JPanel();
        cbAutoChange = new javax.swing.JCheckBox();
        spnTimer = new javax.swing.JSpinner();
        jLabel1 = new javax.swing.JLabel();

        setBorder(null);
        setDoubleBuffered(false);

        java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("datasoul/internationalize"); // NOI18N
        cbAutoChange.setText(bundle.getString("CHANGE EVERY")); // NOI18N
        cbAutoChange.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
        cbAutoChange.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                cbAutoChangeActionPerformed(evt);
            }
        });

        spnTimer.setModel(new SpinnerNumberModel(1, 1, 9999, 1));

        jLabel1.setText(bundle.getString("SECONDS")); // NOI18N

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(cbAutoChange)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(spnTimer, javax.swing.GroupLayout.PREFERRED_SIZE, 37, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jLabel1)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                .addComponent(spnTimer, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addComponent(cbAutoChange)
                .addComponent(jLabel1))
        );

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addComponent(serviceItemTable1, javax.swing.GroupLayout.DEFAULT_SIZE, 242, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addComponent(serviceItemTable1, javax.swing.GroupLayout.DEFAULT_SIZE, 310, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
        );
    }// </editor-fold>//GEN-END:initComponents

    private void cbAutoChangeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbAutoChangeActionPerformed

        if (cbAutoChange.isSelected()){
            automaticChanger.startChanging( Integer.parseInt(spnTimer.getValue().toString()) * 1000 );
        }else{
            automaticChanger.stopChanging();
        }

    }//GEN-LAST:event_cbAutoChangeActionPerformed

    public void setMediaControlsEnabled(boolean b){
        serviceItemTable1.setMediaControlsEnabled(b);
    }

    public void valueChanged(ListSelectionEvent e) {

        // when changing slides with mouse, two events are generated for
        // the same change, one for pressing and other for releasing the mouse button
        // this check avoids processing twice, what makes the transiction effect broken
        if ( serviceItemTable1.getSlideIndex() == lastSelectedIndex || serviceItemTable1.getSlideIndex() < 0){
            return;
        }else{
            lastSelectedIndex = serviceItemTable1.getSlideIndex();
        }
        
        
        ContentManager cm = ContentManager.getInstance();
        cm.saveTransitionImage();
        updateContentValues();
        cm.slideChange(DisplayControlConfig.getInstance().getSlideTransitionTime());
        
    }

    public void updateContentValues(){
        ContentManager cm = ContentManager.getInstance();
        cm.setSlideLive( serviceItemTable1.getSlideText() );
        cm.setNextSlideLive( serviceItemTable1.getNextSlideText() );
        cm.setActiveImageLive(serviceItemTable1.getSlideImage());
        cm.setNextImageLive(serviceItemTable1.getNextSlideImage());
    }
    
    public void serviceNextSlide() {
        int count = serviceItemTable1.getSlideCount();
        int index = serviceItemTable1.getSlideIndex();
        if (index < count-1){
            serviceItemTable1.setSlideIndex(index+1);
        } else {
            goToNextServiceItem();
        }
    }

    private void goToNextServiceItem(){
        if (ObjectManager.getInstance().getDatasoulMainForm().goToNextServiceItem()) {
            if (!DisplayControlConfig.getInstance().getAutomaticGoLiveBool()){
                PreviewPanel pp = ObjectManager.getInstance().getPreviewPanel();
                pp.goLive(false);
            }
        }
    }

    public void servicePreviousSlide() {
        int index = serviceItemTable1.getSlideIndex();
        if (index > 0) {
            serviceItemTable1.setSlideIndex(index-1);
        } else {
            goToPreviousServiceItem();
        }
    }

    private void goToPreviousServiceItem(){
        if (ObjectManager.getInstance().getDatasoulMainForm().goToPreviousServiceItem()) {
            if (!DisplayControlConfig.getInstance().getAutomaticGoLiveBool()){
                SwingUtilities.invokeLater(new Runnable() {
                    @Override
                    public void run() {
                        PreviewPanel pp = ObjectManager.getInstance().getPreviewPanel();
                        pp.goLive(true);
                    }
                });
            }
        }
    }

    public void notifyVideoEnd(){
        serviceItemTable1.notifyVideoEnd();
    }

    public void evtKeyPressed(KeyEvent e){
        if (e.getKeyCode() == KeyEvent.VK_DOWN && serviceItemTable1.getSlideIndex()+1 >= serviceItemTable1.getSlideCount()){
            goToNextServiceItem();
        }
        if (e.getKeyCode() == KeyEvent.VK_UP && serviceItemTable1.getSlideIndex() == 0){
            goToPreviousServiceItem();
        }

    }


    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JCheckBox cbAutoChange;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JPanel jPanel1;
    private datasoul.serviceitems.ServiceItemTable serviceItemTable1;
    private javax.swing.JSpinner spnTimer;
    // End of variables declaration//GEN-END:variables
    
    
    private class AutomaticChanger extends Thread {
        
        boolean stopThread = false;
        long timer;
        
        public AutomaticChanger(){
            this.start();
        }
        
        public void startChanging(int timer){
            this.timer = timer;
            stopThread = false;
            synchronized(this){
                this.notify();
            }
        }
        
        public void stopChanging(){
            stopThread = true;
            this.interrupt();
        }
        
        private void change(){
            
            int maxSlide = serviceItemTable1.getSlideCount();
            int showSlide = serviceItemTable1.getSlideIndex() + 1;

            if (showSlide >= maxSlide){
                showSlide = 0;
            }
            
            serviceItemTable1.setSlideIndex(showSlide);
        }
        
        public void run(){

            long t1, t2;

            while (true){
                
                synchronized(this){
                    try {
                        this.wait();
                    } catch (InterruptedException ex) {
                        ex.printStackTrace();
                    }
                }
                
                while (!stopThread){

                    t1 = System.currentTimeMillis();

                    change();

                    // go sleep!
                    t2 = System.currentTimeMillis();
                    if ( (timer - (t2 - t1)) > 1 ){
                        try {
                            Thread.sleep( timer - (t2 - t1) );
                        } catch (InterruptedException ex) {
                            //ignore. just exist form sleep
                        }
                    }

                }//while stopthread
            }//while true
        }// run
    }
    
}


